package com.miracle.moa.manager.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.miracle.common.Result;
import com.miracle.common.StatusCode;
import com.miracle.common.TokenDecode;
import com.miracle.moa.manager.entity.Permission;
import com.miracle.moa.manager.entity.Role;
import com.miracle.moa.manager.entity.RolePermission;
import com.miracle.moa.manager.entity.User;
import com.miracle.moa.manager.mapper.PermissionMapper;
import com.miracle.moa.manager.service.IPermissionService;
import com.miracle.moa.manager.service.IRolePermissionService;
import com.miracle.moa.manager.service.IUserService;
import lombok.Getter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author miracle
 * @since 2021-03-22
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {

    @Autowired
    private TokenDecode tokenDecode;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private IUserService userService;

    @Autowired
    private IRolePermissionService rolePermissionService;


    @Override
    public Map<String, Object> queryPermissionByUser() {

        Map<String, Object> response = new HashMap<>();
        Map<String, String> userInfo = tokenDecode.getUserInfo();
        /* 用户所属角色 */
        User user = userService.findUserAndRole(MapUtils.getString(userInfo, "username"));
        List<Integer> roles = user.getRoles().stream().map(Role::getId).collect(Collectors.toList());
        List<Permission> permissionTree = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(roles)) {
            Map<String, Object> params = new HashMap<>();
            params.put("list", roles);
            List<Permission> permissions = permissionMapper.queryPermissionByRoles(params);
            permissionTree = this.formatTree(permissions, true);
        }
        response.put("permissions", permissionTree);
        response.put("userInfo", user);
        return response;
    }

    @Override
    public List<Permission> listPermissionTree(String keyword) {
        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(keyword)) {
            /* 根据路由编码和路由名称模糊查询 */
            queryWrapper.lambda().like(Permission::getRouterCode, keyword).or().like(Permission::getLabel, keyword);
        }
        List<Permission> permissions = super.list(queryWrapper);
        return this.formatTree(permissions, true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Permission> listPermissionTreeWithBtn() {
        List<Permission> permissions = super.list();
        return this.formatTree(permissions, false);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result saveOrUpdatePermissions(List<String> btnPerms, Integer parentId) {
        LocalDateTime now = LocalDateTime.now();

        QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId).eq("type", "3");
        List<Permission> permissionList = super.list(queryWrapper);
        /* 需要删除的数据 */
        List<Integer> delIdList = new ArrayList<>();
        for (Permission permission : permissionList) {
            if (!btnPerms.contains(permission.getRouterCode())) {
                delIdList.add(permission.getId());
            } else {
                btnPerms.remove(permission.getRouterCode());
            }
        }

        if (CollectionUtils.isNotEmpty(delIdList)) {
            /* 删除 permission*/
            super.removeByIds(delIdList);
            /* 删除role_permission*/
            QueryWrapper<RolePermission> wrapper = new QueryWrapper<>();
            wrapper.lambda().in(RolePermission::getPermissionId, delIdList);
            rolePermissionService.remove(wrapper);
        }

        if (CollectionUtils.isNotEmpty(btnPerms)) {
            List<Permission> permissions = new ArrayList<>();
            /* 需要保存的按钮数据 */
            for (String btnPerm : btnPerms) {
                Permission permission = new Permission();
                permission.setRouterCode(btnPerm);
                permission.setParentId(parentId);
                permission.setType("3");
                permission.setUpdateTime(now);
                permission.setCreateTime(now);
                permission.setLabel(ButtonNameEnum.getNameByCode(btnPerm));
                permissions.add(permission);
            }
            /* 批量保存或更新 permission*/
            super.saveOrUpdateBatch(permissions);
        }
        return new Result<>(StatusCode.OK, "保存成功");
    }

    /**
     * 按钮枚举
     *
     * @author miracle
     * @since 2021-03-22
     */
    @Getter
    enum ButtonNameEnum {
        SAVE("save", "新建"),
        EDIT("edit", "编辑"),
        DELETE("delete", "删除");

        private String code;

        private String name;

        ButtonNameEnum(String code, String name) {
            this.code = code;
            this.name = name;
        }

        public static String getNameByCode(String code) {
            if (StringUtils.isEmpty(code)) {
                return null;
            }
            ButtonNameEnum[] values = ButtonNameEnum.values();
            for (ButtonNameEnum value : values) {
                if (StringUtils.equals(value.getCode(), code)) {
                    return value.getName();
                }
            }
            return null;
        }

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result deletePermissionById(Integer id) {
        /* 删除权限 */
        super.removeById(id);
        /* 删除所有拥有此权限的角色权限信息*/
        QueryWrapper<RolePermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(RolePermission::getPermissionId, id);
        rolePermissionService.remove(queryWrapper);

        return new Result(StatusCode.OK, "删除成功");
    }

    /**
     * 根据查询到的权限列表，构建权限树
     *
     * @param dataList
     * @return
     */
    private List<Permission> formatTree(List<Permission> dataList, boolean flag) {

        List<Permission> result = new ArrayList<>();
        boolean present = Optional.ofNullable(dataList).isPresent();
        if (present) {
            Map<Integer, List<Permission>> btnGroup = new HashMap<>();
            if (flag) {
                /* 按钮集合 */
                List<Permission> btnList = dataList.stream().filter(p -> StringUtils.equals("3", p.getType())).collect(Collectors.toList());
                /* 将按钮分组 */
                btnGroup = btnList.stream().collect(Collectors.groupingBy(Permission::getParentId));
            }
            /* 执行树转化操作 */
            for (Permission s : dataList) {
                /* 按钮不再继续 */
                if (StringUtils.equals("3", s.getType()) && flag) {
                    continue;
                }
                if (flag) {
                    /* 尝试获取按钮 */
                    List<Permission> permissions = btnGroup.get(s.getId());
                    Optional.ofNullable(permissions).ifPresent(per -> s.setBtnPerms(per.stream().map(Permission::getRouterCode).collect(Collectors.toList())));
                }
                /* 判断是否由子树 */
                boolean getParent = false;
                for (Permission p : dataList) {
                    if (p.getId().equals(s.getParentId())) {
                        List<Permission> sunList = p.getChildren();
                        if (sunList == null) {
                            p.setChildren(new ArrayList<>());
                        }
                        List<Permission> children = p.getChildren();
                        children.add(s);
                        if (!StringUtils.equals("3", s.getType())) {
                            /* 排序 */
                            children.sort(Comparator.comparing(Permission::getOrderNum));
                        }
                        getParent = true;
                        break;
                    }
                }
                if (!getParent) {
                    result.add(s);
                }
            }
        }

        return result;
    }
}
